package com.qf.utils;

import com.sun.org.apache.regexp.internal.RE;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;

/**
 * jdk的动态代理，代理的目标对象，必须是先接口 -- jdk的动态代理只能基于接口
 *      为什么： XxxProxy extends Proxy implements Xxx,Yyy
 */
public class BeanFactory2 {

    public static Object getBean(String beanId)  {

        try {
            Properties properties = new Properties();
            properties.load(BeanFactory2.class.getClassLoader().getResourceAsStream("bean.properties"));

            String className = properties.getProperty(beanId);

            //返回一个功能增强后的对象 -- 动态代理
            //原始对象(目标对象)
            Object obj = Class.forName(className).newInstance();

            //使用CGLIB实现动态代理（不局限于接口代理）
            Class type = obj.getClass(); // 和目标对象类型保持一致

            //实现具体增强逻辑的回调对象，和jdk中的InvocationHandler一致
            Callback invoker = new MethodInterceptor() {
                //intercept就类似于InvocationHandler的invoke方法.当调用代理对象的任何方法，都会执行这个方法

                /*
                    Object o 代理对象  (不常用)
                    Method method 代理对象调用的那个方法
                    Object[] objects 代理对象调用的那个方法的参数
                    MethodProxy methodProxy 目标对象的方法，假设我要调用的是父类的方法，就需要使用到这个对象 （不常用）
                 */
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    //前置增强
                    String methodName = method.getName();

                    if (methodName.startsWith("find")){
                        System.out.println("查询缓存。。。。");
                    }

                    Object invoke = method.invoke(obj, objects);

                    //后置增强
                    System.out.println("后置增强处理");
                    return invoke;
                }
            };
            Object proxy = Enhancer.create(type,invoker);

            return proxy;
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }
}
